/**
 * 防抖函数
 * @param func 需要防抖的函数
 * @param delay 延迟时间（毫秒）
 * @param immediate 是否立即执行（第一次触发时立即执行，之后等待延迟）
 * @returns 经过防抖处理的函数
 */
export function debounce<T extends (...args: any[]) => any, This = any>(
  func: (this: This, ...args: Parameters<T>) => ReturnType<T>,
  delay: number = 500,
  immediate: boolean = false
): (this: This, ...args: Parameters<T>) => void {
  let timer: NodeJS.Timeout | null = null;
  return function (this: This, ...args: Parameters<T>): void {
    // 如果存在定时器，清除它
    if (timer) {
      clearTimeout(timer);
    }
    // 立即执行的情况
    if (immediate && !timer) {
      func.apply(this, args);
    }
    // 设置新的定时器
    timer = setTimeout(() => {
      // 非立即执行的情况，在延迟后执行
      if (!immediate) {
        func.apply(this, args);
      }
      // 执行完成后清空定时器
      timer = null;
    }, delay);
  };
}

/**
 * 节流函数：限制函数在指定时间内只执行一次
 * @param func 需要节流的函数
 * @param wait 节流等待时间（毫秒）
 * @param options 配置选项
 *   - leading: 是否在开始时立即执行一次
 *   - trailing: 是否在结束时再执行一次
 * @returns 节流后的函数
 */
export function throttle<T extends (...args: any[]) => any>(
  func: T,
  wait: number = 500,
  options: { leading?: boolean; trailing?: boolean } = {}
): (...args: Parameters<T>) => void {
  const { leading = true, trailing = true } = options;
  let lastExecTime = 0;
  let timeout: NodeJS.Timeout | null = null;

  return (...args: Parameters<T>): void => {
    const now = Date.now();

    // 如果是第一次执行且不允许 leading 执行，则更新上次执行时间
    if (!lastExecTime && leading === false) {
      lastExecTime = now;
    }

    // 计算剩余等待时间
    const remainingTime = wait - (now - lastExecTime);

    // 如果剩余时间 <= 0，说明可以执行函数
    if (remainingTime <= 0) {
      // 清除可能存在的定时器（防止 trailing 执行）
      if (timeout) {
        clearTimeout(timeout);
        timeout = null;
      }
      // 执行函数并更新上次执行时间
      func.apply(this, args);
      lastExecTime = now;
    }
    // 如果需要 trailing 执行且当前没有定时器
    else if (trailing === true && !timeout) {
      timeout = setTimeout(() => {
        func.apply(this, args);
        lastExecTime = Date.now();
        timeout = null;
      }, remainingTime);
    }
  };
}

/**
 * 查询字典列表
 * @param code 字典编码
 * @returns 字典列表 Promise<{label: string, value: string}[]>
 */
export function getDicList(code: string) {
  return $fetch(`/api/dic/${code}`);
}

/**
 * 将 Blob 对象转换为 File 对象（TypeScript 类型安全版）
 * @param blob 源 Blob 对象
 * @param fileName 文件名（可包含扩展名，如不包含则自动根据 MIME 类型补充）
 * @returns 转换后的 File 对象
 */
export function blobToFile(blob: Blob, fileName: string): File {
  // 从 Blob 的 MIME 类型中提取扩展名（如 'image/png' → 'png'）
  const fileExt = blob.type.split("/")[1] || "bin";
  // 处理文件名：若不含扩展名则自动补充
  const fullFileName = fileName.includes(".")
    ? fileName
    : `${fileName}.${fileExt}`;

  // 通过 File 构造函数转换（File 是 Blob 的子类，类型兼容）
  return new File([blob], fullFileName, { type: blob.type });
}
